﻿using System.Linq;
using System.ComponentModel.Composition;
using Microsoft.VisualStudio.Modeling.Diagrams.ExtensionEnablement; // IVsSelectionContext
using Microsoft.VisualStudio.Modeling.ExtensionEnablement;          // ICommandExtension
using Microsoft.VisualStudio.Modeling.Diagrams;
using System.Collections.Generic;

namespace Project.Co_DataTransformationPrototype.ExtensionEnablement
{
    #region Entity Rename Adaptation Operator
    // Defined in Dsl\MefExtension\DesignerExtensionMetaDataAttribute.cs
    [Co_DataTransformationPrototypeCommandExtension]
    public class RenameEntityCommandClass : ICommandExtension
    {
        /// <summary>
        /// Provides access to current document and selection.
        /// </summary>
        [Import]
        IVsSelectionContext SelectionContext { get; set; }

        /// <summary>
        /// Called when the user selects this command.
        /// </summary>
        /// <param name="command"></param>
        public void Execute(IMenuCommand command)
        {
            Operators.Define(SelectionContext.CurrentStore).RenameOperator(SelectionContext.CurrentSelection.OfType<EntityShape>().ToList());
            
            //Operators.OperatorBuilder.Define(SelectionContext.CurrentStore).CreateTargetEntity(new EntityInfo()).MoveSelectedAttributes(new List<EntityAttribute>());
        }

        /// <summary>
        /// Called when the user right-clicks the diagram.
        /// Determines whether the command should appear.
        /// This method should set command.Enabled and command.Visible.
        /// </summary>
        /// <param name="command"></param>
        public void QueryStatus(IMenuCommand command)
        {
            command.Enabled = command.Visible = (SelectionContext.CurrentSelection.OfType<EntityShape>().Count() > 0);
        }

        /// <summary>
        /// Called when the user right-clicks the diagram.
        /// Determines the text of the command in the menu.
        /// </summary>
        public string Text
        {
            get { return "Rename Element"; }
        }
    }
    #endregion

    #region Entity Remove Adaptation Operator
    [Co_DataTransformationPrototypeCommandExtension]
    public class RemoveEntityCommandClass : ICommandExtension
    {
        /// <summary>
        /// Provides access to current document and selection.
        /// </summary>
        [Import]
        IVsSelectionContext SelectionContext { get; set; }

        /// <summary>
        /// Called when the user selects this command.
        /// </summary>
        /// <param name="command"></param>
        public void Execute(IMenuCommand command)
        {
            Operators.Define(SelectionContext.CurrentStore).RemoveOperator(SelectionContext.CurrentSelection.OfType<EntityShape>().ToList());
        }

        /// <summary>
        /// Called when the user right-clicks the diagram.
        /// Determines whether the command should appear.
        /// This method should set command.Enabled and command.Visible.
        /// </summary>
        /// <param name="command"></param>
        public void QueryStatus(IMenuCommand command)
        {
            command.Enabled = command.Visible = (SelectionContext.CurrentSelection.OfType<EntityShape>().Count() > 0);
        }

        /// <summary>
        /// Called when the user right-clicks the diagram.
        /// Determines the text of the command in the menu.
        /// </summary>
        public string Text
        {
            get { return "Remove Element"; }
        }
    }
    #endregion

    #region Entity Merge Operator
    [Co_DataTransformationPrototypeCommandExtension]
    public class MergeEntityCommandClass : ICommandExtension
    {
        /// <summary>
        /// Provides access to current document and selection.
        /// </summary>
        [Import]
        IVsSelectionContext SelectionContext { get; set; }

        /// <summary>
        /// Called when the user selects this command.
        /// </summary>
        /// <param name="command"></param>
        public void Execute(IMenuCommand command)
        {
            Operators.Define(SelectionContext.CurrentStore).MergeOperator(SelectionContext.CurrentSelection.OfType<EntityShape>().ToList());
        }

        /// <summary>
        /// Called when the user right-clicks the diagram.
        /// Determines whether the command should appear.
        /// This method should set command.Enabled and command.Visible.
        /// </summary>
        /// <param name="command"></param>
        public void QueryStatus(IMenuCommand command)
        {
            command.Enabled = command.Visible = (SelectionContext.CurrentSelection.OfType<EntityShape>().Count() > 1);
        }

        /// <summary>
        /// Called when the user right-clicks the diagram.
        /// Determines the text of the command in the menu.
        /// </summary>
        public string Text
        {
            get { return "Merge Selected Entities..."; }
        }
    }
    #endregion

    #region Entity Splitting Operator
    [Co_DataTransformationPrototypeCommandExtension]
    public class SplitEntityCommandClass : ICommandExtension
    {
        /// <summary>
        /// Provides access to current document and selection.
        /// </summary>
        [Import]
        IVsSelectionContext SelectionContext { get; set; }

        /// <summary>
        /// Called when the user selects this command.
        /// </summary>
        /// <param name="command"></param>
        public void Execute(IMenuCommand command)
        {
            Operators.Define(SelectionContext.CurrentStore).SplitOperator(SelectionContext.CurrentSelection.OfType<EntityShape>().ToList());
        }

        /// <summary>
        /// Called when the user right-clicks the diagram.
        /// Determines whether the command should appear.
        /// This method should set command.Enabled and command.Visible.
        /// </summary>
        /// <param name="command"></param>
        public void QueryStatus(IMenuCommand command)
        {
            command.Enabled = command.Visible = (SelectionContext.CurrentSelection.OfType<EntityShape>().Count() == 1);
        }

        /// <summary>
        /// Called when the user right-clicks the diagram.
        /// Determines the text of the command in the menu.
        /// </summary>
        public string Text
        {
            get { return "Split Entity ..."; }
        }
    }
    #endregion

    #region Move Attributes to Separate Entity
    [Co_DataTransformationPrototypeCommandExtension]
    public class MoveAttributesToTargetEntityCommandClass : ICommandExtension
    {
        /// <summary>
        /// Provides access to current document and selection.
        /// </summary>
        [Import]
        IVsSelectionContext SelectionContext { get; set; }

        /// <summary>
        /// Called when the user selects this command.
        /// </summary>
        /// <param name="command"></param>
        public void Execute(IMenuCommand command)
        {
            List<EntityAttribute> attributeList = SelectionContext.CurrentSelection.OfType<EntityAttribute>().ToList();
            Operators.Define(SelectionContext.CurrentStore).MoveOperator(attributeList, null);
        }

        /// <summary>
        /// Called when the user right-clicks the diagram.
        /// Determines whether the command should appear.
        /// This method should set command.Enabled and command.Visible.
        /// </summary>
        /// <param name="command"></param>
        public void QueryStatus(IMenuCommand command)
        {
            command.Enabled = command.Visible = (SelectionContext.CurrentSelection.OfType<EntityAttribute>().Count() > 0);
        }

        /// <summary>
        /// Called when the user right-clicks the diagram.
        /// Determines the text of the command in the menu.
        /// </summary>
        public string Text
        {
            get { return "Move Attribute To ..."; }
        }
    }
    #endregion

    #region Set Attribute As Primary-Key
    [Co_DataTransformationPrototypeCommandExtension]
    public class SetPrimaryKeyPropertyCommandClass : ICommandExtension
    {
        /// <summary>
        /// Provides access to current document and selection.
        /// </summary>
        [Import]
        IVsSelectionContext SelectionContext { get; set; }

        /// <summary>
        /// Called when the user selects this command.
        /// </summary>
        /// <param name="command"></param>
        public void Execute(IMenuCommand command)
        {
            EntityAttribute attribute = SelectionContext.CurrentSelection.OfType<EntityAttribute>().FirstOrDefault();
            Operators.Define(SelectionContext.CurrentStore).UpdateAttributeProperty<bool>(EntityAttribute.isPrimaryKeyDomainPropertyId, attribute, true);
        }

        /// <summary>
        /// Called when the user right-clicks the diagram.
        /// Determines whether the command should appear.
        /// This method should set command.Enabled and command.Visible.
        /// </summary>
        /// <param name="command"></param>
        public void QueryStatus(IMenuCommand command)
        {
            command.Enabled = command.Visible = (SelectionContext.CurrentSelection.OfType<EntityAttribute>().Count() == 1);
        }

        /// <summary>
        /// Called when the user right-clicks the diagram.
        /// Determines the text of the command in the menu.
        /// </summary>
        public string Text
        {
            get { return "Set as Primary-Key"; }
        }
    }
    #endregion

    #region Remove Attribute Adaptation Operator
    [Co_DataTransformationPrototypeCommandExtension]
    public class RemoveAttributeCommandClass : ICommandExtension
    {
        /// <summary>
        /// Provides access to current document and selection.
        /// </summary>
        [Import]
        IVsSelectionContext SelectionContext { get; set; }

        /// <summary>
        /// Called when the user selects this command.
        /// </summary>
        /// <param name="command"></param>
        public void Execute(IMenuCommand command)
        {
            Operators.Define(SelectionContext.CurrentStore).RemoveOperator(SelectionContext.CurrentSelection.OfType<EntityAttribute>().ToList());
        }

        /// <summary>
        /// Called when the user right-clicks the diagram.
        /// Determines whether the command should appear.
        /// This method should set command.Enabled and command.Visible.
        /// </summary>
        /// <param name="command"></param>
        public void QueryStatus(IMenuCommand command)
        {
            command.Enabled = command.Visible = (SelectionContext.CurrentSelection.OfType<EntityAttribute>().Count() > 0);
        }

        /// <summary>
        /// Called when the user right-clicks the diagram.
        /// Determines the text of the command in the menu.
        /// </summary>
        public string Text
        {
            get { return "Remove Attribute"; }
        }
    }
    #endregion

    #region Attribute Merge Operator
    [Co_DataTransformationPrototypeCommandExtension]
    public class MergeAttributesCommandClass : ICommandExtension
    {
        /// <summary>
        /// Provides access to current document and selection.
        /// </summary>
        [Import]
        IVsSelectionContext SelectionContext { get; set; }

        /// <summary>
        /// Called when the user selects this command.
        /// </summary>
        /// <param name="command"></param>
        public void Execute(IMenuCommand command)
        {
            Operators.Define(SelectionContext.CurrentStore).MergeOperator(SelectionContext.CurrentSelection.OfType<EntityAttribute>().ToList());
        }

        /// <summary>
        /// Called when the user right-clicks the diagram.
        /// Determines whether the command should appear.
        /// This method should set command.Enabled and command.Visible.
        /// </summary>
        /// <param name="command"></param>
        public void QueryStatus(IMenuCommand command)
        {
            command.Enabled = command.Visible = (SelectionContext.CurrentSelection.OfType<EntityAttribute>().Count() > 1);
        }

        /// <summary>
        /// Called when the user right-clicks the diagram.
        /// Determines the text of the command in the menu.
        /// </summary>
        public string Text
        {
            get { return "Merge Selected Attributes ..."; }
        }
    }
    #endregion

    #region Attribute Rename Adaptation Operator
    [Co_DataTransformationPrototypeCommandExtension]
    public class RenameAttributeCommandClass : ICommandExtension
    {
        /// <summary>
        /// Provides access to current document and selection.
        /// </summary>
        [Import]
        IVsSelectionContext SelectionContext { get; set; }

        /// <summary>
        /// Called when the user selects this command.
        /// </summary>
        /// <param name="command"></param>
        public void Execute(IMenuCommand command)
        {
            Operators.Define(SelectionContext.CurrentStore).RenameOperator(SelectionContext.CurrentSelection.OfType<EntityAttribute>().ToList());
        }

        /// <summary>
        /// Called when the user right-clicks the diagram.
        /// Determines whether the command should appear.
        /// This method should set command.Enabled and command.Visible.
        /// </summary>
        /// <param name="command"></param>
        public void QueryStatus(IMenuCommand command)
        {
            command.Enabled = command.Visible = (SelectionContext.CurrentSelection.OfType<EntityAttribute>().Count() > 0);
        }

        /// <summary>
        /// Called when the user right-clicks the diagram.
        /// Determines the text of the command in the menu.
        /// </summary>
        public string Text
        {
            get { return "Rename Attribute"; }
        }
    }
    #endregion

    #region Script Generation from Model
    // Defined in Dsl\MefExtension\DesignerExtensionMetaDataAttribute.cs
    [Co_DataTransformationPrototypeCommandExtension]
    public class GenerateConstraintScriptCommandClass : ICommandExtension
    {
        /// <summary>
        /// Provides access to current document and selection.
        /// </summary>
        [Import]
        IVsSelectionContext SelectionContext { get; set; }

        /// <summary>
        /// Called when the user selects this command.
        /// </summary>
        /// <param name="command"></param>
        public void Execute(IMenuCommand command)
        {
            Data.ScriptUtilities.generateConstraintScriptFromModel(SelectionContext.CurrentStore.ElementDirectory.FindElements<EntityShape>().ToList<EntityShape>());
        }

        /// <summary>
        /// Called when the user right-clicks the diagram.
        /// Determines whether the command should appear.
        /// This method should set command.Enabled and command.Visible.
        /// </summary>
        /// <param name="command"></param>
        public void QueryStatus(IMenuCommand command)
        {
            command.Enabled = command.Visible = (SelectionContext.CurrentSelection.OfType<EntityDiagram>().Count() == 1);
        }

        /// <summary>
        /// Called when the user right-clicks the diagram.
        /// Determines the text of the command in the menu.
        /// </summary>
        public string Text
        {
            get { return "Generate Script from Model"; }
        }
    }
    #endregion

    #region Count Model Elements
    // Defined in Dsl\MefExtension\DesignerExtensionMetaDataAttribute.cs
    [Co_DataTransformationPrototypeCommandExtension]
    public class CountModelElementsCommandClass : ICommandExtension
    {
        /// <summary>
        /// Provides access to current document and selection.
        /// </summary>
        [Import]
        IVsSelectionContext SelectionContext { get; set; }

        /// <summary>
        /// Called when the user selects this command.
        /// </summary>
        /// <param name="command"></param>
        public void Execute(IMenuCommand command)
        {
            ElementCounter.getElementCount(SelectionContext.CurrentStore);
        }

        /// <summary>
        /// Called when the user right-clicks the diagram.
        /// Determines whether the command should appear.
        /// This method should set command.Enabled and command.Visible.
        /// </summary>
        /// <param name="command"></param>
        public void QueryStatus(IMenuCommand command)
        {
            command.Enabled = command.Visible = (SelectionContext.CurrentSelection.OfType<EntityDiagram>().Count() == 1);
        }

        /// <summary>
        /// Called when the user right-clicks the diagram.
        /// Determines the text of the command in the menu.
        /// </summary>
        public string Text
        {
            get { return "Count All Model Elements"; }
        }
    }
    #endregion
}
